/* DECISOES DE PROJETO */
/* 1. qualquer pontuacao marca a separacao de duas frases */
/* 2. palavras sao compostas somentes por letras */
/* 3. decomposicao de dados: cada no ira operar sobre 1/n palavras */

#include"mpi.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>

#define FALSE 	0
#define TRUE 	1
#define ERRO 	-1


/* comparar dois caracteres 'case insensitive' */
int isIgual(char a, char b){

	if(a == b)
		return TRUE;
	else if((a >= 65) && (a <= 90) && (b >= 97) && (b <= 122) && (a == (b -32)))
		return TRUE;
	else if((b >= 65) && (b <= 90) && (a >= 97) && (a <= 122) && (b == (a -32)))
		return TRUE;
	else
		return FALSE;

}

/* verificar se a palavra e um palindromo */
int isPalindromo(char *palavra, int esq, int dir){

	if(palavra == NULL)
		return ERRO;

	if(dir - esq < 0)
		return ERRO;

	if(dir - esq == 0)
		return TRUE;

	else if((dir - esq == 1) && (isIgual(palavra[esq], palavra[dir])))
		return TRUE;

	else if( isIgual(palavra[esq], palavra[dir])){

		esq ++;
		dir --;

		return isPalindromo(palavra, esq, dir);

	}

	return FALSE;
}

/* determinar se o caractere e uma letra */
int isLetra(char c){

	if(((c >= 97) && (c <= 122)) || ((c >= 65) && (c <= 90)))
		return TRUE;

	return FALSE;

}

int isPalavra(char *palavra){

	int i;

	for(i = 0; i < strlen(palavra); ++i)
		if(!isLetra(palavra[i]))
			return FALSE;

	return TRUE;

}

/* remover sinais de pontuacao do fim das palavras */
int removerSinal(char *palavra){

	if(palavra == NULL)
		return ERRO;

	if(!isLetra(palavra[strlen(palavra) - 1])){

		palavra[strlen(palavra) - 1] = '\0';
		return TRUE;

	}
	else
		return FALSE;

}

int isPrimoNum(int num){

	int i;

	if((num == 1) || (num == 2))
		return TRUE;

	for(i = 2; i < (int)sqrt(num) + 1; ++i)
		if(num % i == 0)
			return FALSE;

	return TRUE;

}

int isPrimo(char *palavra){

	int soma = 0, i;

	for(i = 0; i < strlen(palavra); ++i)
		soma += palavra[i];

	return isPrimoNum(soma);

}

int main(int argc, char **argv){

	int totalPalindromos, totalPalindromosPrimos, palindromos, palindromosPrimos; 
	int rank;
	int i, j, nos, end;
	time_t inicio, fim;

	time(&inicio);

	char *lixo = (char*)malloc(1024*sizeof(char));		/* auxiliar para mover o ponteiro do arquivo */
	char *palavra = (char*)malloc(1024*sizeof(char));

	FILE *ifp;

	MPI_Init(&argc, &argv);

 	totalPalindromos = 0;
	totalPalindromosPrimos = 0;
	palindromos = 0;
	palindromosPrimos = 0;
	end = 0;

	ifp = fopen("wikipedia.txt", "rb");

	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &nos);

	printf("no %d\n", nos);

	for( j = 0 ; j < nos ; ++j){

		if(rank == j){

			while(!end){

				for(i = 0; i < j; ++i)			/* colocar o ponteiro na palavra inicial para o processo */
					fscanf(ifp, "%s", lixo);

				if(fscanf(ifp, "%s", palavra) > 0){

					for( ; i < nos - 1 ; ++i) 	/* colocar o ponteiro do arquivo 15 palavras depois*/
						fscanf(ifp, "%s", lixo);

					removerSinal(palavra);

					if(!isPalavra(palavra))
						continue;

					if(isPalindromo(palavra, 0, strlen(palavra) - 1)){

						palindromos++;
						if(isPrimo(palavra))
							palindromosPrimos++;

					}
				}
				else
					end = 1;
			}
		}

	}

	MPI_Reduce(&palindromos,  &totalPalindromos, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); 
	MPI_Reduce(&palindromosPrimos,  &totalPalindromosPrimos, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
	time(&fim);

	if(rank == 0){
		printf("%d palindromos no total, %d cuja soma e um numero primo\n", totalPalindromos, totalPalindromosPrimos);
		printf("execucao: %.f s\n", difftime(fim, inicio));
	}

	free(lixo);
	free(palavra);
	fclose(ifp);

	MPI_Finalize();

	return 0;


}
